package com.mixsmart.utils;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * @author 乌草坡 2022-08-18
 * @since 6.7.2
 */
public class AesGcmUtil {

    public static final String AES = "AES";
    private static final String AES_GCM_PADDING = "AES/GCM/PKCS5Padding";
    public static final int GCM_TAG_LENGTH = 16;

    /*** aesgcm 标准加密 ** @param plaintext * @param keyStr * @param ivStr * @return * @throws Exception
     */
    public static String gcmEncrypt(String plaintext, String keyStr, String ivStr) throws Exception {
        SecretKey key = new SecretKeySpec(Base64.getDecoder().decode(keyStr), AES);
        byte[] iv = Base64.getDecoder().decode(ivStr);
        // Get Cipher Instance
        Cipher cipher = Cipher.getInstance(AES_GCM_PADDING);
        // Create SecretKeySpec
        SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), AES);
        // Create GCMParameterSpec
        GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);
        // Initialize Cipher for ENCRYPT_MODE
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmParameterSpec);
        // Perform Encryption
        byte[] cipherText = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(cipherText);
    }

    /*** aesgcm 标准解密 ** @param cipherText * @param keyStr * @param ivStr * @return * @throws Exception */
    public static String gcmDecrypt(String cipherText, String keyStr, String ivStr) throws Exception {
        SecretKey key = new SecretKeySpec(Base64.getDecoder().decode(keyStr), AES);
        byte[] iv = Base64.getDecoder().decode(ivStr);
        // Get Cipher Instance
        Cipher cipher = Cipher.getInstance(AES_GCM_PADDING);
        // Create SecretKeySpec
        SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), AES);
        // Create GCMParameterSpec
        GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);
        // Initialize Cipher for DECRYPT_MODE
        cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);
        // Perform Decryption
        byte[] decryptedText = cipher.doFinal(Base64.getDecoder().decode(cipherText));
        return new String(decryptedText);
    }

    public static void main(String[] args) {
        try {
            String gcmSecretKey = "MOrnNIk5or7QiGdrmTB2U2Q5In6qWvNDikOGdxrB9Ng=";
            String ivStr = "NLFkRZjUNax4mwuu";
            String toDoStr = "123456789";
            System.out.println("明⽂⽂本：" + toDoStr + "\n");
            String encryptResult2 = gcmEncrypt(toDoStr, gcmSecretKey, ivStr);
            System.out.println("加密结果: " + encryptResult2);
            String decryptResult2 = gcmDecrypt(encryptResult2, gcmSecretKey, ivStr);
            System.out.println("解密结果: " + decryptResult2 + "\n");
        } catch (Exception e) {
            System.out.println("异常,error:" + e);
        }
    }
}
